package com.skyable.auth.config.security;

import com.skyable.auth.config.security.filter.*;
import com.skyable.auth.config.security.handler.CloudAuthenticationSuccessHandler;
import com.skyable.auth.config.security.service.UserDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @author GaoYuan
 * @title: AuthorizationServerConfig
 * @projectName spring-cloud-demo
 * @description: SpringSecurity 基础配置
 *  * 通过继承 WebSecurityConfigurerAdapter 来实现
 * @date 2021/3/2317:55
 */
@Order(1)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailServiceImpl userDetailService;
    @Autowired
    private CloudAuthenticationSuccessHandler cloudAuthenticationSuccessHandler;
    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        // 设置默认的加密方式
        return new BCryptPasswordEncoder();
    }


    /**
     * 认证管理
     * @return 认证管理对象
     * @throws Exception 认证异常信息
     */
//    @Bean
//    @Override
//    public AuthenticationManager authenticationManagerBean() throws Exception {
//        return super.authenticationManagerBean();
//    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailService)
                .passwordEncoder(passwordEncoder());
    }

    /**
     * http安全配置
     * @param http http安全对象
     * @throws Exception http安全异常信息
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http   // 配置登录页并允许访问
                .formLogin()
                    .loginPage("/login")
                    .loginProcessingUrl("/login").permitAll()
                    //TODO Web和OAUTH2 认证成功后需要设置不同的跳转
                    .successHandler(cloudAuthenticationSuccessHandler)
                    .failureHandler(authenticationFailureHandler)
                // 配置Basic登录
                //.and().httpBasic()
                // 配置登出页面
                //.and().logout().logoutUrl("/logout").logoutSuccessUrl("/")
                // 关闭跨域保护;
                .and()
                    .csrf().disable()
                    .authorizeRequests().antMatchers("/user/**").permitAll()
                    // 其余所有请求全部需要鉴权认证
                    .anyRequest().authenticated();
        // 在 UsernamePasswordAuthenticationFilter 前添加 其他认证过滤器
        http.addFilterAt(verificationCodeFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // 将 check_token 暴露出去，否则资源服务器访问时报 403 错误
        web.ignoring().antMatchers(
                "/asserts/**",
                "/error",
                "/static/**",
                "/v2/api-docs/**",
                "/swagger-resources/**",
                "/webjars/**",
                "/favicon.ico"
        );
    }

    @Autowired
    @Qualifier("verificationCodeManager")
    private VerificationCodeManager verificationCodeManager;
    /**
     * 自定义 验证码 过滤器
     */
    private VerificationCodeFilter verificationCodeFilter(){
        VerificationCodeFilter authenticationFilter = new VerificationCodeFilter("/login/code");
        authenticationFilter.setAuthenticationManager(verificationCodeManager);
        authenticationFilter.setAuthenticationSuccessHandler(cloudAuthenticationSuccessHandler);
        authenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler);
        return authenticationFilter;
    }
}